package com.my.zl.console.common.utils.generator;

import java.io.File;
import java.nio.charset.Charset;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.my.zl.common.utils.CopyUtil;
import com.my.zl.common.utils.FreemarkerTool;
import com.my.zl.console.common.utils.generator.bean.CfgConfig;
import com.my.zl.console.common.utils.generator.bean.CfgMain;
import com.my.zl.console.common.utils.generator.bean.CfgMethod;
import com.my.zl.console.common.utils.generator.bean.CfgMethodEntity;
import com.my.zl.console.common.utils.generator.bean.CfgTable;
import com.my.zl.console.common.utils.generator.bean.CfgTableEntity;
import com.my.zl.console.common.utils.generator.bean.CfgTableInterface;
import com.my.zl.console.common.utils.generator.bean.CfgTableRel;
import com.my.zl.console.common.utils.generator.bean.CfgTags;
import com.my.zl.console.common.utils.generator.bean.CfgTemplate;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateConfig.ResourceMode;
import cn.hutool.extra.template.TemplateEngine;
import cn.hutool.extra.template.TemplateUtil;
import cn.hutool.extra.template.engine.beetl.BeetlEngine;
import cn.hutool.extra.template.engine.enjoy.EnjoyEngine;
import cn.hutool.extra.template.engine.thymeleaf.ThymeleafEngine;
import cn.hutool.extra.template.engine.velocity.VelocityEngine;
import cn.hutool.json.JSONUtil;

/**
 * 代码生成入口
 * @author zhouliang
 *
 */
public class ZLGenerator {
    private static final Logger LOGGER = LoggerFactory.getLogger(ZLGenerator.class);
    
    private static final Pattern field_rule1 = Pattern.compile("\\{[U|L]{0,1}A_[_A-Za-z0-9]+\\}",Pattern.CASE_INSENSITIVE);
    private static final Pattern field_rule2 = Pattern.compile("\\{[U|L]{0,1}B_[_A-Za-z0-9]+\\}",Pattern.CASE_INSENSITIVE);
    private static final Pattern field_rule3 = Pattern.compile("\\{[U|L]{0,1}C_[_A-Za-z0-9]+\\}",Pattern.CASE_INSENSITIVE);
    private static final Pattern field_rule4 = Pattern.compile("\\{[U|L]{0,1}D_[_A-Za-z0-9]+\\}",Pattern.CASE_INSENSITIVE);
    
    private static final Pattern s_rule1 = Pattern.compile("\\b(/)+\\b");
    private static final Pattern s_rule2 = Pattern.compile("[A-Z0-9a-z]+");
    private static final Pattern s_rule3 = Pattern.compile("^([A-Za-z]){1}([A-Z]){1}([a-z]){1}");
    
    // 初始化配置参数
    @SuppressWarnings("unchecked")
    public static String entry(List<CfgConfig> cfgConfigs){
        long start = System.currentTimeMillis();
        try{
            if(cfgConfigs == null || cfgConfigs.size() == 0){
                return null;
            }
            
            String time = DateTimeFormatter.ofPattern(ZLGeneratorE.TIME_STR.getCode2())
                    .withLocale(Locale.SIMPLIFIED_CHINESE).withZone(ZoneId.systemDefault()).format(Instant.now());
            String date = DateTimeFormatter.ofPattern(ZLGeneratorE.DATE_STR.getCode2())
                    .withLocale(Locale.SIMPLIFIED_CHINESE).withZone(ZoneId.systemDefault()).format(Instant.now());
            
            //最终完整数据
            Map<String,List<Map<String,Object>>> dataAll = new LinkedHashMap<>();
            //最终完整数据
            Map<String, CfgConfig> dataConfigAll = new LinkedHashMap<>();
            //最终完整数据
            Map<String,Map<String,String>> tagsAll = new LinkedHashMap<>();
            
            //联动时保证模块编码不同
            Map<String,String> linkTagsMap = new LinkedHashMap<>();
            Map<String,Map<String,Object>> linkDatasMap = new LinkedHashMap<>();
            Map<String,Map<String,Object>> linkDatasMap2 = new LinkedHashMap<>();
            //TODO
            Map<String,CfgTable> linkTablesMap = new LinkedHashMap<>();
            List<CfgTableRel> linkTableRels = new ArrayList<>();
            List<String> linkImportTableClass= new ArrayList<>();
            List<String> linkResourceMapperClass = new ArrayList<>();
            
            Map<String,CfgConfig> cfgLinkMap = new HashMap<>();
            for(CfgConfig cfgConfig :cfgConfigs){
                if("2".equals(cfgConfig.getGenerateType())){
                    List<CfgTemplate> dataTemplate = cfgConfig.getTemplateJSON();
                    if(cfgConfig.getMainJSON() == null || dataTemplate == null || dataTemplate.size() == 0){
                        continue;
                    }
                    Map<String,List<CfgTemplate>> templateDataMap = dataTemplate.stream().filter(x->("4".equals(x.getOutputType()) || "5".equals(x.getOutputType()))
                            && StringUtils.isNotBlank(x.getOutputFileName()) && StringUtils.isNotBlank(x.getOutputFileFormat())).collect(Collectors.groupingBy(x->x.getFromKeyCode()));
                    if(templateDataMap==null || templateDataMap.isEmpty()){
                        continue;
                    }
                    if(cfgConfig.getTableJSON() != null && cfgConfig.getTableJSON().size() > 0){
                        for(CfgTable tablex : cfgConfig.getTableJSON()){
                            if(cfgLinkMap.get(tablex.getTableJavaCode())==null && StringUtils.isNotBlank(tablex.getSelectTemplate())){//不加载模板则联动模块中的
                                List<CfgTemplate> dataTemplate2 = templateDataMap.get(tablex.getTableJavaCode());
                                if(dataTemplate2!= null && dataTemplate2.size()>0){
                                    CfgConfig cfg2 = new CfgConfig();
                                    cfg2.setTemplateJSON(CopyUtil.copyList(dataTemplate2, CfgTemplate.class));
                                    cfg2.getTemplateJSON().stream().forEach(x->x.setLoadTemplate("0"));
                                    List<CfgTable> dataTable2 = new ArrayList<>();
                                    dataTable2.add(BeanUtil.toBean(tablex, CfgTable.class));
                                    cfg2.setTableJSON(dataTable2);
                                    cfgLinkMap.put(tablex.getTableJavaCode(), cfg2);
                                }
                            }
                        }
                    }
                }
            }
            
            for(int i=0,sn=cfgConfigs.size(); i < sn; i++){
                try{
                    CfgConfig cfgConfig = cfgConfigs.get(i);
                    
                    List<CfgTemplate> dataTemplate = cfgConfig.getTemplateJSON();
                    if(cfgConfig.getMainJSON() == null || dataTemplate == null || dataTemplate.size() == 0){
                        continue;
                    }
                    
                    List<CfgTemplate> templateDataMain = dataTemplate.stream().filter(x->"1".equals(x.getOutputType())
                            && StringUtils.isNotBlank(x.getOutputFileName()) && StringUtils.isNotBlank(x.getOutputFileFormat())).collect(Collectors.toList());
                    List<CfgTemplate> templateDataMethod = dataTemplate.stream().filter(x->("2".equals(x.getOutputType()) || "3".equals(x.getOutputType()) || "6".equals(x.getOutputType()) )
                            && StringUtils.isNotBlank(x.getOutputFileName()) && StringUtils.isNotBlank(x.getOutputFileFormat())).collect(Collectors.toList());
                    List<CfgTemplate> templateDataTable = dataTemplate.stream().filter(x->("4".equals(x.getOutputType()) || "5".equals(x.getOutputType()))
                            && StringUtils.isNotBlank(x.getOutputFileName()) && StringUtils.isNotBlank(x.getOutputFileFormat())).collect(Collectors.toList());
                    
                    if(cfgConfig.getTableJSON()!=null && cfgConfig.getTableJSON().size()>0){
                        if(templateDataTable == null){
                            templateDataTable = new ArrayList<>();
                        }
                        for(CfgTable tablex : cfgConfig.getTableJSON()){
                            CfgConfig cfgVo = cfgLinkMap.get(tablex.getTableJavaCode());
                            if(StringUtils.isBlank(tablex.getSelectTemplate()) && cfgVo!=null){//不加载模板则取联动模块中的
                                tablex = cfgVo.getTableJSON().get(0);
                                templateDataTable.addAll(cfgVo.getTemplateJSON());
                            }
                        }
                    }
                    
                    if((templateDataMain == null || templateDataMain.size() == 0) && (templateDataMain == null || templateDataMethod.size() == 0)
                            && (templateDataTable == null || templateDataTable.size() == 0)){
                        continue;
                    }
                    
                    //新的数据
                    List<CfgTemplate> newTemplates = new ArrayList<>();
                    CfgMain newMain = new CfgMain();
                    List<CfgMethod> newMethods = new ArrayList<>();
                    Map<String,CfgMethod> methodMap = new LinkedHashMap<>();
                    List<CfgTable> newTables = new ArrayList<>();
                    Map<String,CfgTable> tableMap = new LinkedHashMap<>();
                    List<CfgTableRel> tableRels = new ArrayList<>();
                    Map<String,List<CfgTableRel>> tableRelsMap = new LinkedHashMap<>();
                    Map<String,List<CfgTableRel>> childTableRelsMap = new LinkedHashMap<>();
                    //处理模块
                    doHandleDataForMain(cfgConfig, newTemplates,templateDataMain, newMain);
                    //处理方法
                    doHandleDataForMethod(cfgConfig, newTemplates, templateDataMethod, newMain, newMethods, methodMap);
                    //处理表
                    doHandleDataForTable(cfgConfig, newTemplates, templateDataTable, newMain, newTables
                            , tableMap, tableRels, tableRelsMap, childTableRelsMap);
                    
                    //处理主表
                    CfgTable mainTableVo = null;
                    if(newTables.size() == 1){
                        mainTableVo = newTables.get(0);
                    }else if(newTables.size() > 1){
                        List<CfgTable> needList =newTables.stream().filter(tblx->"1".equals(tblx.getNeedFlag())).collect(Collectors.toList());
                        if(needList !=null && needList.size() > 0){
                            mainTableVo = needList.get(0);
                        }
                    }
                    
                    //TODO
                    List<Map<String, Object>> dataRoot = new ArrayList<>();//当前数据
                    Map<String,String> tagsMap = new LinkedHashMap<>();//当前标签
                    Map<String,Map<String, String>> methodTagsMap = new LinkedHashMap<>();//方法标签
                    Map<String,Map<String, String>> tableTagsMap = new LinkedHashMap<>();//表标签
                    List<CfgTags> importTags = new ArrayList<>();//需要引入方法/表类
                    
                    for(CfgTemplate tv:newTemplates) {
                        Map<String, Object> myRootMap = new LinkedHashMap<>();
                        Map<String, String> myTagMap = new LinkedHashMap<>();
                        myRootMap.put(ZLGeneratorE.BASE_PACK.getCode(), "import "+cfgConfig.getBasePackagePath());
                        myRootMap.put(ZLGeneratorE.MODULE_PACK.getCode(), "import "+cfgConfig.getBasePackagePath() + "." + cfgConfig.getOutputPackagePath());
                        myRootMap.put(ZLGeneratorE.BASE_PATH.getCode(), cfgConfig.getOutputRootPath());
                        myRootMap.put(ZLGeneratorE.TIME_STR.getCode(), time);
                        myRootMap.put(ZLGeneratorE.DATE_STR.getCode(), date);
                        myRootMap.put(ZLGeneratorE.AUTHOR_STR.getCode(), cfgConfig.getTagAuthor());
                        myRootMap.put(ZLGeneratorE.EXPLAIN_STR.getCode(), cfgConfig.getTagExplain1());
                        myRootMap.put(ZLGeneratorE.EXPLAIN_STR.getCode2(), cfgConfig.getTagExplain2());
                        myRootMap.put(ZLGeneratorE.TITLE_STR.getCode(), cfgConfig.getProjectTitle());
                        myRootMap.put(ZLGeneratorE.TITLE_STR.getCode2(), cfgConfig.getModuleTitle());
                        
                        myRootMap.put(ZLGeneratorE.DATA_TEMPLATE.getCode(), tv);
                        myRootMap.put(ZLGeneratorE.DATA_MAIN.getCode(), newMain);
                        myRootMap.put(ZLGeneratorE.DATA_METHOD.getCode(), newMethods);
                        myRootMap.put(ZLGeneratorE.DATA_METHOD.getCode2(), methodMap);
                        myRootMap.put(ZLGeneratorE.DATA_TABLE.getCode(), newTables);
                        myRootMap.put(ZLGeneratorE.DATA_TABLE.getCode2(), tableMap);
                        myRootMap.put(ZLGeneratorE.TABLE_REL.getCode(), childTableRelsMap);
                        //方法
                        if("3".equals(tv.getOutputType()) || "2".equals(tv.getOutputType())){
                            String mdxKey = tv.getFromKeyCode();
                            CfgMethod methodx = methodMap.get(mdxKey);
                            myRootMap.put(ZLGeneratorE.METHOD_OWN.getCode(), methodx);
                            myRootMap.put(ZLGeneratorE.DATA_TYPE.getCode2(), mdxKey);
                        }
                        //方法-子对象
                        else if("6".equals(tv.getOutputType())){
                            String[] keys = tv.getFromKeyCode().split(",");
                            String mdxKey = keys[0];
                            CfgMethod methodx = methodMap.get(mdxKey);
                            List<CfgMethodEntity> entitys = methodx.getOrderEntitys().get(keys[1]);
                            for(CfgMethodEntity edto : entitys){
                                if(edto.getFieldJavaCode().equals(keys[2])){
                                    myRootMap.put(ZLGeneratorE.ENTITY_OWN.getCode(), edto);
                                    break;
                                }
                            }
                            myRootMap.put(ZLGeneratorE.METHOD_OWN.getCode(), methodx);
                            myRootMap.put(ZLGeneratorE.DATA_TYPE.getCode2(), mdxKey);
                        }
                        //表
                        else if("4".equals(tv.getOutputType()) || "5".equals(tv.getOutputType())){
                            String tableKey = tv.getFromKeyCode();
                            CfgTable tablex = tableMap.get(tableKey);
                            myRootMap.put(ZLGeneratorE.TABLE_OWN.getCode(), tablex);
                            myRootMap.put(ZLGeneratorE.DATA_TYPE.getCode(), tableKey);
                        }
                        //模块
                        else if("1".equals(tv.getOutputType())){
                            
                        }
                        
                        
                        //自身路径(JAVA文件为包路径,其它为文件路径),方便自身调用
                        boolean javaFlag = tv.getOutputFileFormat().equalsIgnoreCase("java");
                        
                        
                        if(javaFlag){
                            String lastPackPath = "import "+tv.getLastPackPath()+";";
                            String lastOwnPackPath = "package "+tv.getLastOwnPackPath()+";";
                            String lastFileName = tv.getOutputFileName();
                            
                            String lastFileNameNew = lastFileName;
                            String uname = StringUtils.capitalize(lastFileNameNew);
                            String lname = StringUtils.uncapitalize(lastFileNameNew);
                            if(StringUtils.isNotBlank(cfgConfig.getSuffixOverride())){
                                lastFileNameNew =  StringUtils.uncapitalize(lastFileNameNew);
                                String[] arr = cfgConfig.getSuffixOverride().split("[\\|,，]");
                                for(String x: arr){
                                    if(StringUtils.isNotBlank(x)){
                                        x = x.trim();
                                        if(lastFileNameNew.substring(0,x.length()).equalsIgnoreCase(x)){
                                            lastFileNameNew = lastFileNameNew.substring(x.length());
                                            break;
                                        }
                                    }
                                }
                            }else{
                                Matcher m3 = s_rule3.matcher(lastFileNameNew);
                                if(m3.find()){
                                    lastFileNameNew = lastFileName.substring(1);
                                }
                            }
                            
                            uname = StringUtils.capitalize(lastFileNameNew);
                            lname = StringUtils.uncapitalize(lastFileNameNew);
                            myRootMap.put(ZLGeneratorE.PACK_OWN.getCode(), lastOwnPackPath);
                            myRootMap.put(ZLGeneratorE.NAME_OWN.getCode(), lastFileName);
                            myRootMap.put(ZLGeneratorE.UNAME_OWN.getCode(), uname);
                            myRootMap.put(ZLGeneratorE.LNAME_OWN.getCode(), lname);
                            
                            myTagMap.put(ZLGeneratorE.PACK_OWN.getCode2() + tv.getFromQuoteTag(), lastPackPath);
                            myTagMap.put(ZLGeneratorE.NAME_OWN.getCode2() + tv.getFromQuoteTag(), lastFileName);
                            myTagMap.put(ZLGeneratorE.UNAME_OWN.getCode2() + tv.getFromQuoteTag(), uname);
                            myTagMap.put(ZLGeneratorE.LNAME_OWN.getCode2() + tv.getFromQuoteTag(), lname);
                            myTagMap.put(ZLGeneratorE.PACK_OWN.getCode3() + tv.getFromQuoteTag(), tv.getLastPackPath());
                            
                            
                            tagsMap.put(ZLGeneratorE.PACK_OWN.getCode2() + tv.getQuoteTag(), lastPackPath);
                            tagsMap.put(ZLGeneratorE.NAME_OWN.getCode2() + tv.getQuoteTag(), lastFileName);
                            tagsMap.put(ZLGeneratorE.UNAME_OWN.getCode2() + tv.getQuoteTag(), uname);
                            tagsMap.put(ZLGeneratorE.LNAME_OWN.getCode2() + tv.getQuoteTag(), lname);
                            tagsMap.put(ZLGeneratorE.PACK_OWN.getCode3() + tv.getQuoteTag(), tv.getLastPackPath());
                            
                            if("2".equals(cfgConfig.getGenerateType())){
                                String extagStr = "";
                                if("1".equals(tv.getOutputType())){
                                    extagStr ="_"+newMain.getModuleKey();
                                }
                                linkTagsMap.put(ZLGeneratorE.PACK_OWN.getCode2() + tv.getQuoteTag()+extagStr, lastPackPath);
                                linkTagsMap.put(ZLGeneratorE.NAME_OWN.getCode2() + tv.getQuoteTag()+extagStr, lastFileName);
                                linkTagsMap.put(ZLGeneratorE.UNAME_OWN.getCode2() + tv.getQuoteTag()+extagStr, uname);
                                linkTagsMap.put(ZLGeneratorE.LNAME_OWN.getCode2() + tv.getQuoteTag()+extagStr, lname);
                                linkTagsMap.put(ZLGeneratorE.PACK_OWN.getCode3() + tv.getQuoteTag()+extagStr, tv.getLastPackPath());
                            }
                            
                            if("1".equals(tv.getNeedFlag())){
                                CfgTags tagVo = new CfgTags();
                                tagVo.setType(tv.getOutputType());
                                tagVo.setImportPack(lastPackPath);
                                tagVo.setName(lastFileName);
                                tagVo.setLname(lname);
                                tagVo.setUname(uname);
                                importTags.add(tagVo);
                            }
                        }else{
                            String lastPackPath = tv.getLastPackPath();
                            String lastFileName = tv.getOutputFileName()+"."+tv.getOutputFileFormat();
                            
                            int pathNums = s_rule1.split(lastPackPath).length-1;
                            String relativePath = "";
                            for(int pi=0; pi < pathNums ;pi++){
                                relativePath = relativePath + "../";
                            }
                            
                            String uname = StringUtils.capitalize(lastFileName);
                            String lname = StringUtils.uncapitalize(lastFileName);
                            myRootMap.put(ZLGeneratorE.PACK_OWN.getCode(), lastPackPath);
                            myRootMap.put(ZLGeneratorE.NAME_OWN.getCode(), lastFileName);
                            myRootMap.put(ZLGeneratorE.UNAME_OWN.getCode(), uname);
                            myRootMap.put(ZLGeneratorE.LNAME_OWN.getCode(), lname);
                            myRootMap.put(ZLGeneratorE.LEVEL_OWN.getCode(), relativePath);
                            
                            myTagMap.put(ZLGeneratorE.PACK_OWN.getCode2() + tv.getFromQuoteTag(), lastPackPath);
                            myTagMap.put(ZLGeneratorE.NAME_OWN.getCode2() + tv.getFromQuoteTag(), lastFileName);
                            myTagMap.put(ZLGeneratorE.UNAME_OWN.getCode2() + tv.getFromQuoteTag(), uname);
                            myTagMap.put(ZLGeneratorE.LNAME_OWN.getCode2() + tv.getFromQuoteTag(), lname);
                            myTagMap.put(ZLGeneratorE.LEVEL_OWN.getCode2() + tv.getFromQuoteTag(), relativePath);
                            
                            tagsMap.put(ZLGeneratorE.PACK_OWN.getCode2() + tv.getQuoteTag(), lastPackPath);
                            tagsMap.put(ZLGeneratorE.NAME_OWN.getCode2() + tv.getQuoteTag(), lastFileName);
                            tagsMap.put(ZLGeneratorE.UNAME_OWN.getCode2() + tv.getQuoteTag(), uname);
                            tagsMap.put(ZLGeneratorE.LNAME_OWN.getCode2() + tv.getQuoteTag(), lname);
                            tagsMap.put(ZLGeneratorE.LEVEL_OWN.getCode2() + tv.getQuoteTag(), relativePath);
                            
                            if("2".equals(cfgConfig.getGenerateType())){
                                String extagStr = "";
                                if("1".equals(tv.getOutputType())){
                                    extagStr ="_"+newMain.getModuleKey();
                                }
                                linkTagsMap.put(ZLGeneratorE.PACK_OWN.getCode2() + tv.getQuoteTag()+extagStr, lastPackPath);
                                linkTagsMap.put(ZLGeneratorE.NAME_OWN.getCode2() + tv.getQuoteTag()+extagStr, lastFileName);
                                linkTagsMap.put(ZLGeneratorE.UNAME_OWN.getCode2() + tv.getQuoteTag()+extagStr, uname);
                                linkTagsMap.put(ZLGeneratorE.LNAME_OWN.getCode2() + tv.getQuoteTag()+extagStr, lname);
                                linkTagsMap.put(ZLGeneratorE.LEVEL_OWN.getCode2() + tv.getQuoteTag()+extagStr, relativePath);
                            }
                        }
                        
                        if("4".equals(tv.getOutputType()) || "5".equals(tv.getOutputType())){
                            String tableKey = tv.getFromKeyCode();
                            if(tableTagsMap.containsKey(tableKey)){
                                tableTagsMap.get(tableKey).putAll(myTagMap);
                            }else{
                                tableTagsMap.put(tableKey, myTagMap);
                            }
                        } else if("2".equals(tv.getOutputType()) || "3".equals(tv.getOutputType()) || "6".equals(tv.getOutputType())){
                            String mdxKey = tv.getFromKeyCode();
                            if(methodTagsMap.containsKey(mdxKey)){
                                methodTagsMap.get(mdxKey).putAll(myTagMap);
                            }else{
                                methodTagsMap.put(mdxKey, myTagMap);
                            }
                        }
                        
                        dataRoot.add(myRootMap);
                    }
                    
                    List<String> importMethodClass= new ArrayList<>();
                    List<String> importMethodClass2= new ArrayList<>();
                    List<String> importTableClass= new ArrayList<>();
                    List<String> resourceTableClass= new ArrayList<>();
                    for(CfgTags t:importTags){
                        if("2".equals(t.getType()) || "3".equals(t.getType()) || "6".equals(t.getType())){
                            importMethodClass.add(t.getImportPack());
                        }
                        if("2".equals(t.getType()) || "3".equals(t.getType())){
                            importMethodClass2.add(t.getImportPack());
                        }
                        if("4".equals(t.getType()) || "5".equals(t.getType())){
                            
                            importTableClass.add(t.getImportPack());
                            
                            String rsmapper = t.getName() +" "+ t.getLname();
                            if("5".equals(t.getType()) && !resourceTableClass.contains(rsmapper)){
                                resourceTableClass.add(rsmapper);
                            }
                            if("2".equals(cfgConfig.getGenerateType())){
                                if(!linkImportTableClass.contains(t.getImportPack())){
                                    linkImportTableClass.add(t.getImportPack());
                                }
                                if("5".equals(t.getType()) && !linkResourceMapperClass.contains(rsmapper)){
                                    linkResourceMapperClass.add(rsmapper);
                                }
                            }
                        }
                    }
                    newMain.setImportAll(importTags);
                    newMethods.forEach(x->{
                        x.setTags(methodTagsMap.get(x.getMethodKey()));
                    });
                    newTables.forEach(x->{
                        x.setTags(tableTagsMap.get(x.getTableJavaCode()));
                    });
                    //同模块使用
                    for(Map<String, Object> x:dataRoot){
                        x.put(ZLGeneratorE.DATA_IMPORT_METHOD.getCode(), importMethodClass.size()>0?StringUtils.join(importMethodClass, "\n"):null);
                        x.put(ZLGeneratorE.DATA_IMPORT_METHOD.getCode2(), importMethodClass2.size()>0?StringUtils.join(importMethodClass2, "\n"):null);
                        x.put(ZLGeneratorE.DATA_IMPORT_TABLE.getCode(), importTableClass.size()>0?StringUtils.join(importTableClass, "\n"):null);
                        x.put(ZLGeneratorE.DATA_RESOURCE.getCode2(), "    @Autowired\n    private "+StringUtils.join(resourceTableClass,";\n    @Autowired\n    private ")+";");
                        
                        //合并
                        String dataType =  (String)x.get(ZLGeneratorE.DATA_TYPE.getCode());
                        if(StringUtils.isNotBlank(dataType) && tableTagsMap.get(dataType) != null){
                            x.putAll(tableTagsMap.get(dataType));
                        }
                        String dataType2 =  (String)x.get(ZLGeneratorE.DATA_TYPE.getCode2());
                        if(StringUtils.isNotBlank(dataType2) && methodTagsMap.get(dataType2) != null){
                            x.putAll(methodTagsMap.get(dataType2));
                        }
                        //主表处理
                        CfgTemplate cTemplate = (CfgTemplate) x.get(ZLGeneratorE.DATA_TEMPLATE.getCode());
                        if(!"4".equals(cTemplate.getOutputType()) && !"5".equals(cTemplate.getOutputType())
                                && mainTableVo != null){
                            x.put(ZLGeneratorE.TABLE_OWN.getCode(), mainTableVo);
                            x.putAll(((CfgTable)x.get(ZLGeneratorE.TABLE_OWN.getCode())).getTags());
                        }
                        
                        x.put(ZLGeneratorE.DATA_TAG.getCode(), tagsMap);
                        x.putAll(tagsMap);
                    }
                    if(mainTableVo != null){//主表放一下
                        tagsMap.putAll(mainTableVo.getTags());
                    }
                    
                    dataAll.put(i+"", dataRoot);
                    
                    CfgConfig cfgConfigVo = new CfgConfig();
                    cfgConfigVo.setCharacterEncoding(cfgConfig.getCharacterEncoding());
                    cfgConfigVo.setTemplatePath(cfgConfig.getTemplatePath());
                    cfgConfigVo.setGenerateType(cfgConfig.getGenerateType());
                    cfgConfigVo.setCfgGeneratePath(cfgConfig.getCfgGeneratePath());
                    dataConfigAll.put(i+"", cfgConfigVo);
                    
                    tagsAll.put(i+"", tagsMap);
                    
                    //1独立，2联动
                    if("2".equals(cfgConfig.getGenerateType())){
                        
                        if(newTables.size()>0){
                            tableMap.forEach((k,v)->{
                                if(!linkTablesMap.containsKey(k)){
                                    linkTablesMap.put(k,v);
                                }
                            });
                        }
                        if(tableRels.size()>0){
                            tableRels.forEach(x->{
                                boolean hasrelFlag = false;
                                if(linkTableRels.size()>0){
                                    for(CfgTableRel lx: linkTableRels){
                                        if(lx.getCTableCode().equals(x.getCTableCode()) && lx.getCColumnJavaCode().equals(x.getCColumnJavaCode())
                                            && lx.getPTableCode().equals(x.getPTableCode()) && lx.getPColumnJavaCode().equals(x.getPColumnJavaCode())){
                                            hasrelFlag = true;
                                            break;
                                        }
                                    }
                                }
                                if(!hasrelFlag){
                                    linkTableRels.add(x);
                                }
                            });
                        }
                        
                        Map<String, Object> linkDataVo = new HashMap<>();
                        linkDataVo.put(ZLGeneratorE.DATA_MAIN.getCode(), newMain);
                        linkDataVo.put(ZLGeneratorE.DATA_METHOD.getCode(), newMethods);
                        linkDataVo.put(ZLGeneratorE.DATA_METHOD.getCode2(), methodMap);
                        linkDataVo.put(ZLGeneratorE.DATA_TABLE.getCode(), newTables);
                        linkDataVo.put(ZLGeneratorE.DATA_TABLE.getCode2(), tableMap);
                        linkDatasMap.put(ZLGeneratorE.DATA_OTHER.getCode2() + newMain.getModuleKey(), linkDataVo);
                        linkDatasMap2.put(newMain.getModuleKey(), linkDataVo);
                    }
                }catch(Exception e){
                    LOGGER.info("配置异常>>第{}条,{}",(i+1),e);
                }
            }
            
            if(dataAll.size()>0){
                dataAll.forEach((k,v) -> {
                    CfgConfig cConfig = dataConfigAll.get(k);
                    Map<String,String> ctag = tagsAll.get(k);
                    
                    List<File> allfiles = FileUtil.loopFiles(cConfig.getTemplatePath());
                    if(allfiles == null || allfiles.size()==0){
                        return;
                    }
                    if(StringUtils.isNotBlank(cConfig.getCfgGeneratePath())){
                        FileUtil.clean(cConfig.getCfgGeneratePath());
                    }
                    
                    Map<String,TemplateEngine> engineMap = new HashMap<>();
                    if(allfiles.get(0).getName().toLowerCase().endsWith("btl") || allfiles.get(0).getName().toLowerCase().endsWith("vtl")
                            || allfiles.get(0).getName().toLowerCase().endsWith("ejy") || allfiles.get(0).getName().toLowerCase().endsWith("tlf")){
                        
                        TemplateConfig engineConfig = new TemplateConfig(Charset.forName(cConfig.getCharacterEncoding()),cConfig.getTemplatePath(), ResourceMode.FILE);
                        
                        if(allfiles.get(0).getName().toLowerCase().endsWith("btl")){
                            engineConfig.setCustomEngine(BeetlEngine.class);
                        }else if(allfiles.get(0).getName().toLowerCase().endsWith("vtl")){
                            engineConfig.setCustomEngine(VelocityEngine.class);
                        }else if(allfiles.get(0).getName().toLowerCase().endsWith("ejy")){
                            engineConfig.setCustomEngine(EnjoyEngine.class);
                        }else if(allfiles.get(0).getName().toLowerCase().endsWith("tlf")){
                            engineConfig.setCustomEngine(ThymeleafEngine.class);
                        }
                        
                        TemplateEngine tEngine = TemplateUtil.createEngine(engineConfig);
                        engineMap.put("tEngine", tEngine);
                    }
                    else{
                        FreemarkerTool.initFreemarker(cConfig.getTemplatePath());
                    }
                    
                    v.stream().forEach(rx ->{
                        CfgTemplate cTemplate = (CfgTemplate) rx.get(ZLGeneratorE.DATA_TEMPLATE.getCode());
                        rx.remove(ZLGeneratorE.DATA_TEMPLATE.getCode());
                        
                        CfgMain newMain = (CfgMain)rx.get(ZLGeneratorE.DATA_MAIN.getCode());
                        
                        //引用其它模块的路径
                        
                        List<CfgTable> newTables = (List<CfgTable>) rx.get(ZLGeneratorE.DATA_TABLE.getCode());
                        newTables.forEach(tblx ->{
                            tblx.setTableData(doHandleOtherClassPath(ctag,tblx.getTableData()));
                            List<CfgTableInterface> sqls = tblx.getSqlInterfaces();
                            if(sqls != null && sqls.size() >0){
                                sqls.stream().forEach(x ->{
                                    x.setParameterType(doHandleOtherClassPath(ctag,x.getParameterType()));
                                    x.setReturnType(doHandleOtherClassPath(ctag,x.getReturnType()));
                                    x.setParameterTypeXml(doHandleOtherClassPath(ctag,x.getParameterTypeXml()));
                                    x.setReturnTypeXml(doHandleOtherClassPath(ctag,x.getReturnTypeXml()));
                                    x.setTableData(doHandleOtherClassPath(ctag,x.getTableData()));
                                });
                            }
                        });
                        List<CfgMethod> newMethods = (List<CfgMethod>) rx.get(ZLGeneratorE.DATA_METHOD.getCode());
//                        Map<String, CfgMethod> newMethodMap = (Map<String,CfgMethod>) rx.get(ZLGeneratorE.DATA_METHOD.getCode2());
                        newMethods.forEach(mdx ->{
                            Map<String, List<CfgMethodEntity>> dtos1 = mdx.getEntityData();
                            dtos1.forEach((dtk,dtv) ->{
                                if(dtv!=null && dtv.size()>0){
                                    doHandleEntitysTags(dtv, ctag);
                                    doHandleEntitysTags(dtv, linkTagsMap);
                                }
                            });
                        });
                        
                        String importClazz = doHandleOtherClassPath(ctag, cTemplate.getImportClazz());
                        String autowiredClazz = doHandleOtherClassPath(ctag, cTemplate.getAutowiredClazz());
                        String extendClazz = doHandleOtherClassPath(ctag, cTemplate.getExtendClazz());
                        importClazz = doHandleOtherClassPath(linkTagsMap, importClazz);
                        autowiredClazz = doHandleOtherClassPath(linkTagsMap, autowiredClazz);
                        extendClazz = doHandleOtherClassPath(linkTagsMap, extendClazz);
                        
                        rx.put(ZLGeneratorE.DATA_CLASS.getCode(), importClazz);
                        rx.put(ZLGeneratorE.DATA_RESOURCE.getCode(), autowiredClazz);
                        rx.put(ZLGeneratorE.DATA_EXTENDS.getCode(), extendClazz);
                        rx.put(ZLGeneratorE.DATA_FILE.getCode(), cTemplate.getImportFile());
                        
                        if("2".equals(cConfig.getGenerateType())){
                            rx.putAll(linkDatasMap);
                            if(linkDatasMap2 !=null && linkDatasMap2.size()>0){
                                rx.put(ZLGeneratorE.DATA_OTHER.getCode(),linkDatasMap2);
                            }else{
                                rx.put(ZLGeneratorE.DATA_OTHER.getCode(),null);
                            }
                            rx.putAll(linkTagsMap);
                            if(newTables==null || newTables.size()==0){
                                if(linkImportTableClass.size()>0){
                                    rx.put(ZLGeneratorE.DATA_IMPORT_TABLE.getCode(), StringUtils.join(linkImportTableClass,"\n"));
                                }
                                if(linkResourceMapperClass.size()>0){
                                    rx.put(ZLGeneratorE.DATA_RESOURCE.getCode2(), "    @Autowired\n    private "+StringUtils.join(linkResourceMapperClass,";\n    @Autowired\n    private ")+";");
                                }
                                rx.put(ZLGeneratorE.TABLE_REL.getCode(), linkTableRels);
                                rx.put(ZLGeneratorE.DATA_TABLE.getCode2(), linkTablesMap);
                            }
                        }
                        
                        if("1".equals(cTemplate.getLoadTemplate())){
                            if(allfiles.get(0).getName().toLowerCase().endsWith("btl") || allfiles.get(0).getName().toLowerCase().endsWith("vtl")
                                    || allfiles.get(0).getName().toLowerCase().endsWith("ejy")|| allfiles.get(0).getName().toLowerCase().endsWith("tlf")){
                                Template template = engineMap.get("tEngine").getTemplate(cTemplate.getFileName());
                                template.render(rx, new File(cTemplate.getLastCreatePath()));
                            }
                            else{
                                FreemarkerTool.processFile(rx , cConfig.getCharacterEncoding()
                                        , cTemplate.getFileName(), cTemplate.getLastCreatePath());
                            }
                        }
                        
                        System.out.println(newMain.getModuleKey()+"  >>>>  "+cTemplate.getLastOwnPackPath()+"---"+cTemplate.getLastFilePath()+"---"+cTemplate.getLastPackPath());
                    });
                });
            }
        }catch(Exception e){
            LOGGER.info("代码生成异常>>{}",e);
        }
        String usetime = (System.currentTimeMillis() - start) / 1000F + "s";
        LOGGER.info("Use time:" + usetime);
        return usetime;
    }
    
    private static void doHandleDataForMain(CfgConfig cfgConfig,List<CfgTemplate> newTemplates,List<CfgTemplate> templateDataMain
            , CfgMain newMain){
        cfgConfig.setCharacterEncoding(StringUtils.isNotBlank(cfgConfig.getCharacterEncoding()) ? cfgConfig.getCharacterEncoding() : "UTF-8");
        
        String generatePath = cfgConfig.getCfgGeneratePath();
        generatePath = generatePath.replaceAll("(\\\\)+|(/)+", "/");
        if (!generatePath.endsWith("/") ) {// 防止目录路径没有结束符
            generatePath = generatePath + "/";
        }
        cfgConfig.setCfgGeneratePath(generatePath);
        
        //处理模块
        String mainxStr = JSONUtil.toJsonStr(cfgConfig.getMainJSON());
        mainxStr = doHandleFieldKeyValueAll(mainxStr, cfgConfig.getMainJSON(), cfgConfig.getMainJSON().getFieldEx(), "1");
//        newMain = JSONUtil.toBean(mainxStr, CfgMain.class);
        BeanUtil.copyProperties(JSONUtil.toBean(mainxStr, CfgMain.class), newMain);
        
        for(CfgTemplate tx : templateDataMain){
            if(!"1".equals(cfgConfig.getMainJSON().getLoadTemplate())){
                tx.setLoadTemplate("0");
            }
            
            String templateStr = JSONUtil.toJsonStr(tx);
            templateStr = doHandleFieldKeyValueAll(templateStr, newMain, newMain.getFieldEx(), "1");
            CfgTemplate txVO = JSONUtil.toBean(templateStr, CfgTemplate.class);
            
            
            doHandleWholePath(cfgConfig, newMain, txVO, newTemplates);
        }
    }
    private static void doHandleDataForMethod(CfgConfig cfgConfig,List<CfgTemplate> newTemplates
            ,List<CfgTemplate> templateDataMethod,CfgMain newMain,List<CfgMethod> newMethods,Map<String,CfgMethod> methodMap){
        if(cfgConfig.getMethodJSON() != null && cfgConfig.getMethodJSON().size() > 0){
            for(CfgMethod methodx : cfgConfig.getMethodJSON()){
                String methodxStr = JSONUtil.toJsonStr(methodx);
                methodxStr = doHandleFieldKeyValueAll(methodxStr, newMain, newMain.getFieldEx(), "1");
                methodxStr = doHandleFieldKeyValueAll(methodxStr, methodx, methodx.getFieldEx(), "2");
                CfgMethod methodVO = JSONUtil.toBean(methodxStr, CfgMethod.class);
                
                Map<String, List<CfgMethodEntity>> entityJSON = methodVO.getEntityData();
                if(entityJSON != null && entityJSON.size() > 0){
                    Map<String, List<CfgMethodEntity>> orderEntitys = new LinkedHashMap<>();
                    Map<String, Map<String,List<CfgMethodEntity>>> groupEntitys = new LinkedHashMap<>();
                    Map<String, Map<String,String>> groupNames = new LinkedHashMap<>();
                    
                    Map<String,List<CfgMethodEntity>> dictEntitys = new LinkedHashMap<>();
                    
                    entityJSON.forEach((ek,ev)->{
                        if(ev == null || ev.size() == 0 || ev.get(0).getChildren() == null 
                                || ev.get(0).getChildren().size() == 0){
                            entityJSON.put(ek, null);
                        }
                        else {
                            //处理对象字段值
                            doHandleEntityFieldValue(ev.get(0).getChildren(),newMain,methodx);
                            
                            //这里不需要根节点
                            //排序,降序
                            List<CfgMethodEntity> orderlist = doHandleEntityOrder(ev.get(0).getChildren());
                            orderEntitys.put(ek, orderlist);
                            
                            //分组
                            Map<String,List<CfgMethodEntity>> grouplt =  new LinkedHashMap<>();
                            Map<String,String> groupnm = new LinkedHashMap<>();
                            doHandleEntityGroup(orderlist,grouplt,groupnm);
                            groupEntitys.put(ek, grouplt);
                            groupNames.put(ek, groupnm);
                            
                            doHandleEntityDict(ev, dictEntitys);
                        }
                        
                    });
                    
                    methodVO.setGroupEntitys(groupEntitys);
                    methodVO.setGroupNames(groupNames);
                    methodVO.setOrderEntitys(orderEntitys);
                }
                
                methodMap.put(methodVO.getMethodKey(), methodVO);
                
                newMethods.add(methodVO);
            }
            
            
            for(CfgTemplate tx : templateDataMethod){
                if("6".equals(tx.getOutputType())){
                    continue;
                }
                if("1".equals(cfgConfig.getMainJSON().getLoadTemplate())){
                    tx.setLoadTemplate("1".equals(tx.getLoadTemplate())?"1":"0");
                }
                String mdxKey = tx.getFromKeyCode();
                CfgMethod methodx = methodMap.get(mdxKey);
                
                tx.setNeedFlag(!"1".equals(methodx.getNeedFlag())?"0":"1");
                
                String templateStr = JSONUtil.toJsonStr(tx);
                templateStr = doHandleFieldKeyValueAll(templateStr, newMain, newMain.getFieldEx(), "1");
                templateStr = doHandleFieldKeyValueAll(templateStr, methodx, methodx.getFieldEx(), "2");
                CfgTemplate txVO = JSONUtil.toBean(templateStr, CfgTemplate.class);
                
                doHandleWholePath(cfgConfig, newMain, txVO, newTemplates);
            }
            for(CfgTemplate tx : templateDataMethod){
                if(!"6".equals(tx.getOutputType())){
                    continue;
                }
                if("1".equals(cfgConfig.getMainJSON().getLoadTemplate())){
                    tx.setLoadTemplate("1".equals(tx.getLoadTemplate())?"1":"0");
                }
                String[] keys = tx.getFromKeyCode().split(",");
                CfgMethod methodx = methodMap.get(keys[0]);
                
                tx.setNeedFlag(!"1".equals(methodx.getNeedFlag())?"0":"1");
                
                List<CfgMethodEntity> entitys = methodx.getOrderEntitys().get(keys[1]);
                for(CfgMethodEntity edto : entitys){
                    if(edto.getFieldJavaCode().equals(keys[2])){
                        String templateStr = JSONUtil.toJsonStr(tx);
                        templateStr = doHandleFieldKeyValueAll(templateStr, newMain, newMain.getFieldEx(), "1");
                        templateStr = doHandleFieldKeyValueAll(templateStr, methodx, methodx.getFieldEx(), "2");
                        templateStr = doHandleFieldKeyValueAll(templateStr, edto, edto.getFieldEx(), "4");
                        CfgTemplate txVO = JSONUtil.toBean(templateStr, CfgTemplate.class);
                        
                        doHandleWholePath(cfgConfig, newMain, txVO, newTemplates);
                        
                        break;
                    }
                }
            }
        }
    }
            
    private static void doHandleDataForTable(CfgConfig cfgConfig,List<CfgTemplate> newTemplates,List<CfgTemplate> templateDataTable
            , CfgMain newMain,List<CfgTable> newTables,Map<String,CfgTable> tableMap,List<CfgTableRel> tableRels
            ,Map<String,List<CfgTableRel>> tableRelsMap,Map<String,List<CfgTableRel>> childTableRelsMap){
        if(cfgConfig.getTableJSON() != null && cfgConfig.getTableJSON().size() > 0){
            for(CfgTable tablex : cfgConfig.getTableJSON()){
                if(tablex.getTableRels()!=null&&tablex.getTableRels().size()>0){
                    tableRels.addAll(tablex.getTableRels());
                    tableRelsMap.put(tablex.getTableJavaCode(), tablex.getTableRels());
                }
                
                String tablexStr = JSONUtil.toJsonStr(tablex);
                tablexStr = doHandleFieldKeyValueAll(tablexStr, newMain, newMain.getFieldEx(), "1");
                tablexStr = doHandleFieldKeyValueAll(tablexStr, tablex, null, "3");
                CfgTable tableVO = JSONUtil.toBean(tablexStr, CfgTable.class);
                
                List<CfgTableEntity> ownEntity = tablex.getOwnEntity();
                List<CfgTableEntity> generalEntity = new ArrayList<>();
                List<CfgTableEntity> primaryEntity = new ArrayList<>();
                List<CfgTableEntity> otherEntity = new ArrayList<>();
                for(CfgTableEntity oe : ownEntity){
                    if("1".equals(oe.getPrimarykeyFlag())){
                        primaryEntity.add(oe);
                    }else{
                        generalEntity.add(oe);
                    }
                }
                List<CfgTableInterface> sqlInterfaces = tablex.getSqlInterfaces();
                
                Map<String,CfgTableInterface> sqlInterfacesMap = new HashMap<>();
                if(sqlInterfaces!=null && sqlInterfaces.size() > 0){
                    List<String> hasField = new ArrayList<>();
                    for(CfgTableInterface sx : sqlInterfaces){
                        sx.setNeedFlag(!"1".equals(sx.getNeedFlag())?"0":"1");
                        List<CfgTableEntity> edt = sx.getEntityData();
                        if(edt!=null && edt.size() > 0){
                            for(CfgTableEntity ex : edt){
                                String keyx = ex.getColumnCode()+"-"+ex.getColumnJavaCode2();
                                if("1".equals(ex.getLoadFlag()) && !hasField.contains(keyx)){
                                    hasField.add(keyx);
                                    otherEntity.add(ex);
                                }
                            }
                        }
                        
                        sqlInterfacesMap.put(sx.getSqlCode(), sx);
                    }
                }
                
                tableVO.setSqlInterfacesMap(sqlInterfacesMap);
                tableVO.setPrimaryEntity(primaryEntity);
                tableVO.setGeneralEntity(generalEntity);
                tableVO.setOtherEntity(otherEntity);
                
                tableMap.put(tableVO.getTableJavaCode(), tableVO);
                
                newTables.add(tableVO);
            }
            
            
            for(CfgTemplate tx : templateDataTable){
                if("1".equals(cfgConfig.getMainJSON().getLoadTemplate())){
                    tx.setLoadTemplate("1".equals(tx.getLoadTemplate())?"1":"0");
                }
                String tableKey = tx.getFromKeyCode();
                CfgTable tablex = tableMap.get(tableKey);
                
                tx.setNeedFlag(!"1".equals(tablex.getNeedFlag())?"0":"1");
                
                String templateStr = JSONUtil.toJsonStr(tx);
                templateStr = doHandleFieldKeyValueAll(templateStr, newMain, newMain.getFieldEx(), "1");
                templateStr = doHandleFieldKeyValueAll(templateStr, tablex, null, "3");
                CfgTemplate txVO = JSONUtil.toBean(templateStr, CfgTemplate.class);
                
                doHandleWholePath(cfgConfig, newMain, txVO, newTemplates);
            }
        }
        
        if(tableRels.size()>0){
            //如果有主从关系，加上反向关联
            tableRels.forEach(lt->{
                List<CfgTableRel> tblrel = childTableRelsMap.get(lt.getCTableJavaCode());
                if(tblrel==null){
                    tblrel = new ArrayList<>();
                    childTableRelsMap.put(lt.getCTableJavaCode(), tblrel);
                }
                CfgTableRel tblrelVo = BeanUtil.copyProperties(lt, CfgTableRel.class);
                tblrelVo.setPTableType(tableMap.get(tblrelVo.getPTableJavaCode()).getTableType());
                tblrelVo.setCTableType(tableMap.get(tblrelVo.getCTableJavaCode()).getTableType());
                tblrel.add(tblrelVo);
            });
        }
    }
    
    
    private static void doHandleEntitysTags(List<CfgMethodEntity> elist,Map<String,String> linkTagsMap){
        elist.stream().forEach(ltx->{
            ltx.setJavaType(doHandleOtherClassPath(linkTagsMap,  ltx.getJavaType()));
            ltx.setJavaFullType(doHandleOtherClassPath(linkTagsMap,  ltx.getJavaFullType()));
            ltx.setJavaVoType(doHandleOtherClassPath(linkTagsMap,  ltx.getJavaVoType()));
            if(StringUtils.isBlank(ltx.getUseModuleCode())){
                ltx.setUseModuleCode(null);
            }
            if(StringUtils.isBlank(ltx.getUseMethodCode())){
                ltx.setUseMethodCode(null);
            }
            if(StringUtils.isBlank(ltx.getUseTableCode())){
                ltx.setUseTableCode(null);
            }
            if(StringUtils.isBlank(ltx.getUseTableSqlCode())){
                ltx.setUseTableSqlCode(null);
            }
            if(ltx.getChildren()!=null && ltx.getChildren().size()>0){
                doHandleEntitysTags(ltx.getChildren(), linkTagsMap);
            }
        });
    }
    
    
    private static void doHandleWholePath(CfgConfig cfgConfig, CfgMain dataMain, CfgTemplate txVO, List<CfgTemplate> templates){
        if("0".equals(dataMain.getLoadTemplate())){//不加载
            txVO.setLoadTemplate("0");
        }
        
        //引入类路径
        txVO.setImportClazz(doHandleImportClass(txVO.getImportClazz()));
        //载入类
        txVO.setAutowiredClazz(doHandleRecourceClass(txVO.getAutowiredClazz()));
        //继承类
        txVO.setExtendClazz(doHandleExtendsClass(txVO.getExtendClazz()));
        //引入文件
        txVO.setImportFile(txVO.getImportFile());
        
        String outputBasePath = txVO.getOutputBasePath();
        String outputPath = txVO.getOutputPath();
        String outputFileName = txVO.getOutputFileName();
        String outputFileFormat = txVO.getOutputFileFormat();
        
        String lastPath = "";
        if(StringUtils.isNotBlank(outputBasePath)){
            lastPath = outputBasePath + "/";
        }
        if(StringUtils.isNotBlank(outputPath)){
            lastPath = lastPath + outputPath + "/";
        }
        String lastOwnPath = lastPath;
        lastPath = lastPath + outputFileName;
        
        String basePack = cfgConfig.getBasePackagePath();
        if(StringUtils.isNotBlank(cfgConfig.getOutputPackagePath())){
            basePack = basePack +"."+cfgConfig.getOutputPackagePath();
        }
        
        lastPath = lastPath.replaceAll("(\\\\)+|(/)+", ".");
        lastOwnPath = lastOwnPath.replaceAll("(\\\\)+|(/)+", ".");
        if(lastOwnPath.endsWith(".")){
            lastOwnPath = lastOwnPath.substring(0,lastOwnPath.length()-1);
        }
        
        String lastPath2 = lastPath.replaceAll("(\\.)+", "/") +"."+ outputFileFormat;
        
        txVO.setLastFilePath(lastPath2);
        txVO.setLastCreatePath(cfgConfig.getCfgGeneratePath() + lastPath2);
        if(outputFileFormat.equalsIgnoreCase("java")){
            txVO.setLastPackPath(basePack +"."+lastPath);
            txVO.setLastOwnPackPath(basePack +"."+lastOwnPath);
        }else{
            txVO.setLastPackPath(lastPath.replaceAll("(\\.)+", "/") +"."+ outputFileFormat);
        }
        
        templates.add(txVO);
    }
    
    private static String doHandleFieldKeyValueAll(String value,Object beanObj, Map<String,String> mapEx,String type){
        if(StringUtils.isBlank(value)){
            return "";
        }
        if(!value.contains("{") || !value.contains("}")){
            return value;
        }
        Matcher m = null;
        
        String mk ="";
        if("1".equals(type)){
            mk = "A_";
            m = field_rule1.matcher(value);
        }else if("2".equals(type)){
            mk = "B_";
            m = field_rule2.matcher(value);
        }else if("3".equals(type)){
            mk = "C_";
            m = field_rule3.matcher(value);
        }else if("4".equals(type)){
            mk = "D_";
            m = field_rule4.matcher(value);
        }
        
        while(m.find()){
            String fgroup = m.group();
            String fstr = fgroup.replaceAll("\\{|\\}", "");
            String fstr2 = fstr.toUpperCase();
            String ckey = null;
            if(fstr2.startsWith(mk)){
                ckey = fstr.substring(2);
            }else if(fstr2.startsWith("U"+mk)){
                ckey = fstr.substring(3);
            }else if(fstr2.startsWith("L"+mk)){
                ckey = fstr.substring(3);
            }
            Object cval = ReflectUtil.getFieldValue(beanObj, ckey);
            if(cval == null){
                if(mapEx != null && mapEx.containsKey(ckey)){
                    cval = mapEx.get(ckey);
                }
            }
            if(cval == null){
                cval = "";
            }
            String cnval = cval.toString();
            if(StringUtils.isNotBlank(cnval)){
                if(fstr2.startsWith("U"+mk)){
                    cnval = StringUtils.capitalize(cnval);
                }else if(fstr2.startsWith("L"+mk)){
                    cnval = StringUtils.uncapitalize(cnval);
                }else if(fstr2.startsWith(mk)){

                }
            }
            fstr = "\\{" + fstr + "\\}";
            value = value.replaceAll(fstr, cnval);
        }
        
        return value;
    }
    
    private static String doHandleImportClass(String importClazz){
        Set<String> clazzs = new HashSet<>();
        if(StringUtils.isNotBlank(importClazz)){
            String[] importClazzArr = importClazz.trim().split("(\n){0,}( ){0,}(;;){1,}( ){0,}(\n){0,}");
            for(String clazzx : importClazzArr){
                if(StringUtils.isNotBlank(clazzx)){
                    clazzx = clazzx.trim();
                    if(!clazzx.contains("{") && !clazzx.contains("}") ){
                        if(!clazzx.contains("import ")){
                            clazzx = "import " + clazzx;
                        }
                        if(!clazzx.endsWith(";")){
                            clazzx = clazzx + ";";
                        }
                    }
                    clazzs.add(clazzx);
                }
            }
        }
        if(clazzs.size()>0){
            return clazzs.stream().collect(Collectors.joining("\n"));
        }
        return null;
    }
    
    private static String doHandleRecourceClass(String recourceClazz){
        Set<String> clazzs = new HashSet<>();
        if(StringUtils.isNotBlank(recourceClazz)){
            String[] recourceClazzArr = recourceClazz.trim().split("(\n){0,}( ){0,}(;;){1,}( ){0,}(\n){0,}");
            for(String clazzx : recourceClazzArr){
                if(StringUtils.isNotBlank(clazzx)){
                    clazzx = clazzx.trim();
                    if(!clazzx.contains("@Autowired") && !clazzx.contains("@Resource")){
                        clazzx = "    @Resource\n" + clazzx;
                    }
                    if(!clazzx.endsWith(";")){
                        clazzx = clazzx + ";";
                    }
                    clazzs.add(clazzx);
                }
            }
        }
        
        if(clazzs.size()>0){
            return clazzs.stream().collect(Collectors.joining("\n"));
        }
        return null;
    }
    
    private static String doHandleExtendsClass(String extendsClazz){
        if(StringUtils.isNotBlank(extendsClazz)){
            String clazzx = extendsClazz;
            if(!clazzx.contains("extends ")){
                clazzx = "extends " + clazzx;
            }
            
            return clazzx;
        }
        return null;
    }
    
    
    private static String doHandleOtherClassPath(Map<String,String> linkTagsMap, String value){
        if(StringUtils.isBlank(value)){
            return null;
        }
        if(value.contains("{") && value.contains("}") ){
            for(Entry<String, String> x :linkTagsMap.entrySet()){
                String k = x.getKey();
                String v = x.getValue();
                String keycode = "{"+k+"}";
                if(value.contains(keycode)){
                    value = value.replace(keycode, v);
                }
            }
        }
        return value;
    }
    
    public static void doHandleEntityFieldValue(List<CfgMethodEntity> ev, CfgMain newMain, CfgMethod methodx){
        for(CfgMethodEntity x : ev){
            x.setInputOptions1(x.getInputOptions2());//强制把该值同步
            
            String entityxStr = JSONUtil.toJsonStr(x);
            entityxStr = doHandleFieldKeyValueAll(entityxStr, newMain, newMain.getFieldEx(), "1");
            entityxStr = doHandleFieldKeyValueAll(entityxStr, methodx, methodx.getFieldEx(), "2");
            entityxStr = doHandleFieldKeyValueAll(entityxStr, x, x.getFieldEx(), "4");
            BeanUtil.copyProperties(JSONUtil.toBean(entityxStr,CfgMethodEntity.class), x,false);
            
            List<CfgMethodEntity> children = x.getChildren();
            if(children != null && children.size()>0){
                doHandleEntityFieldValue(children,newMain,methodx);
            }
        }
    }
    
    public static List<CfgMethodEntity> doHandleEntityOrder(List<CfgMethodEntity> ev){
        List<CfgMethodEntity> orderlist = ev.stream().sorted(Comparator.comparing(CfgMethodEntity::getPageOrder).reversed()).collect(Collectors.toList());
        for(CfgMethodEntity x : orderlist){
            List<CfgMethodEntity> children = x.getChildren();
            if(children != null && children.size()>0){
                x.setChildren(doHandleEntityOrder(children));
            }
        }
        return orderlist;
    }
    
    
    public static List<CfgMethodEntity> doHandleEntityDict(List<CfgMethodEntity> ev,Map<String,List<CfgMethodEntity>> dictEntitys){
        for(CfgMethodEntity x : ev){
            if(StringUtils.isNotBlank(x.getInputDict())){
                List<CfgMethodEntity> dictlist = dictEntitys.get(x.getInputDict());
                if(dictlist==null){
                    dictlist = new ArrayList<>();
                }
                if(!dictlist.stream().anyMatch(dx->x.getFieldJavaCode().equals(dx.getFieldJavaCode()))){
                    dictlist.add(x);
                }
                dictEntitys.put(x.getInputDict(), dictlist);
            }
            List<CfgMethodEntity> children = x.getChildren();
            if(children != null && children.size()>0){
                doHandleEntityDict(children,dictEntitys);
            }
        }
        return ev;
    }
    
    
    public static void doHandleEntityGroup(List<CfgMethodEntity> orderlist,  Map<String,List<CfgMethodEntity>> grouplt
            , Map<String,String> groupnm){
        for(CfgMethodEntity oltx : orderlist){
            String groupCode = oltx.getGroupCode();
            String groupName = oltx.getGroupName();
            groupCode = StringUtils.isBlank(groupCode)?"N":groupCode.trim();
            groupName = StringUtils.isBlank(groupName)?"":groupName.trim();
            
            if(groupnm.containsKey(groupCode)){
                if(StringUtils.isBlank(groupnm.get(groupCode)) && StringUtils.isNotBlank(groupName)){
                    groupnm.put(groupCode, groupName);
                }else if("N".equalsIgnoreCase(groupCode) && StringUtils.isNotBlank(groupName)){
                    groupnm.put(groupCode, groupName);
                }
            }else{
                if("N".equalsIgnoreCase(groupCode) && StringUtils.isBlank(groupName)){
                    groupnm.put(groupCode, "默认");
                }else{
                    groupnm.put(groupCode, groupName);
                }
            }
            
            List<CfgMethodEntity> orderex = grouplt.get(groupCode);
            if(orderex == null){
                orderex = new ArrayList<>();
            }
            orderex.add(oltx);
            grouplt.put(groupCode, orderex);
        }
    }
}
